#ifndef DTEADDIN_H_E212DF6C_4B8E_4DDE_9653_D9262759406F
#define DTEADDIN_H_E212DF6C_4B8E_4DDE_9653_D9262759406F
/**
 * \file DTEAddIn.h
 *
 * \brief Header file for class CDTEAddIn
 *
 * $Id: DTEAddIn.h,v 1.2 2008/04/26 16:04:24 mgh Exp $
 *
 *
 * Copyright (C) 2006, 2008 Michael G. Herstine <sp1ff@pobox.com>
 *
 * Permission to use, copy, or modify this source code is hereby granted
 * free of  charge, provided  that this copyright  notice appear  on all
 * copies  and  on   all  source  code  derived  from   this  code.   No
 * representation is made regarding the suitability of this software for
 * any  purpose.  It  is provided  "as  is" without  express or  implied
 * warranty.
 *
 *
 */

#ifndef STDAFX_H_10C3F2AB_C971_462D_AE43_8D659E613A34
# error "#include 'stdafx.h' before this file for PCH!"
#endif // not "stdafx.h"

#ifndef RESOURCE_H_INCLUDED
# include "resource.h"          // Resource definitions
#endif // not "resource.h"

#ifndef SAMPLECAI_H_INCLUDED
# include "SampleCAI.h"         // MIDL-generated COM bindings
#endif // not "SampleCAI.h"

#include "viagui.h"
#include "commands.h"

class CAddIn;                   // Used in the interface, below
class CDTEAddIn;                // Forward declaration for class
                                // CWindowEventsSink
/**
 * \class CWindowEventSink
 *
 * \brief C++ class sinking Visual Studio's Window-related events
 *
 *
 */

class CWindowEventsSink:
  public IDispEventImpl<1,
                        CWindowEventsSink,
                        &__uuidof(EnvDTE::_dispWindowEvents),
                        &EnvDTE::LIBID_EnvDTE, 8, 0>
{
public:
  /// Construct with a reference to our owner
  CWindowEventsSink(CDTEAddIn *pParent);

# ifndef DOXYGEN_INVOKED        // Shield the macros from doxygen...
  BEGIN_SINK_MAP(CWindowEventsSink)
    SINK_ENTRY_EX(1,__uuidof(EnvDTE::_dispWindowEvents),1,WindowClosing)
    SINK_ENTRY_EX(1,__uuidof(EnvDTE::_dispWindowEvents),2,WindowMoved)
    SINK_ENTRY_EX(1,__uuidof(EnvDTE::_dispWindowEvents),3,WindowActivated)
    SINK_ENTRY_EX(1,__uuidof(EnvDTE::_dispWindowEvents),4,WindowCreated)
    END_SINK_MAP()
# endif // not DOXYGEN_INVOKED

public:
  void __stdcall WindowClosing(EnvDTE::Window *Window);
  void __stdcall WindowMoved(EnvDTE::Window *Window, long Top,
                             long Left, long Width, long Height);
  void __stdcall WindowActivated(EnvDTE::Window *GotFocus,
                                 EnvDTE::Window *LostFocus);
  void __stdcall WindowCreated(EnvDTE::Window *Window);

 private:
  CDTEAddIn *m_pParent;

}; // End CWindowEventsSink.

extern _ATL_FUNC_INFO OnClickButtonInfo;

/**
 * \class CDTEAddIn
 *
 * \sa CAddIn
 *
 * \brief Incarnates the SAMPLECAI.CoDTEAddIn Com component
 *
 *
 * \note This component is not externally creatble; it is only meant to
 * be aggregated into CoAddIn.
 *
 *
 */

class ATL_NO_VTABLE CDTEAddIn :
  public CComObjectRootEx<CComSingleThreadModel>,
  public CComCoClass<CDTEAddIn, &CLSID_CoDTEAddIn>,
  public ISupportErrorInfo,
  public IDispatchImpl<EnvDTE::IDTCommandTarget,
                       &EnvDTE::IID_IDTCommandTarget,
                       &EnvDTE::LIBID_EnvDTE,
                       7,
                       0>,
  public IDispatchImpl<AddInDO::_IDTExtensibility2,
                       &AddInDO::IID__IDTExtensibility2,
                       &AddInDO::LIBID_AddInDesignerObjects,
                       1,
                       0>,
  // N.B. We only want to sink a few events fired through this
  // interface, so we use IDispEventSimplImpl rather than
  // IDispatchImpl, which requires that the entire interface
  // be implemented.
  public IDispEventSimpleImpl<1,
                              CDTEAddIn,
                              &__uuidof(Office::_CommandBarButtonEvents)>,
  public IDispEventSimpleImpl<2,
                              CDTEAddIn,
                              &__uuidof(Office::_CommandBarButtonEvents)>
{
public:
  /// Application host flavors
  enum Host
  {
    /// Sentinel value
    Host_Unknown,
    /// Visual Studio 2003
    Host_VS2003,
    /// Visual Studio 2005 or later
    Host_VS2005,
    /// Excel 2003
    Host_Excel2003,

    // Add new hosts here...

  };

public:
  /// ATL requires a default ctor
  CDTEAddIn();
  /// ATL-defined initialization routine
  HRESULT FinalConstruct();
  /// ATL-defined cleanup routine
  void FinalRelease();
  /// VisEmacs initialization routine
  void SetParam(CAddIn *pParent);

# ifndef DOXYGEN_INVOKED        // Shield the macros from doxygen...
  /// Tell the ATL Registrar *not* to register us
  DECLARE_NO_REGISTRY();
  /// This component may only be created as an aggregate
  DECLARE_ONLY_AGGREGATABLE(CDTEAddIn)
  /// Tell ATL which interfaces we support
  BEGIN_COM_MAP(CDTEAddIn)
    COM_INTERFACE_ENTRY(ISupportErrorInfo)
    COM_INTERFACE_ENTRY(EnvDTE::IDTCommandTarget)
    COM_INTERFACE_ENTRY(AddInDO::_IDTExtensibility2)
    COM_INTERFACE_ENTRY2(IDispatch, AddInDO::IDTExtensibility2)
  END_COM_MAP()
  BEGIN_SINK_MAP(CDTEAddIn)
    SINK_ENTRY_INFO(1, __uuidof(Office::_CommandBarButtonEvents),/*dispid*/ 0x01, OnClickCfg, &OnClickButtonInfo)
    SINK_ENTRY_INFO(2, __uuidof(Office::_CommandBarButtonEvents),/*dispid*/ 0x01, OnClickSay, &OnClickButtonInfo)
  END_SINK_MAP()
# endif // not DOXYGEN_INVOKED

  //////////////////////////////////////////////////////////////////////
  // Interface ISupportsErrorInfo
public:
  STDMETHOD(InterfaceSupportsErrorInfo)(/*[in]*/ REFIID riid);

  //////////////////////////////////////////////////////////////////////
  // IDTCommandTarget
public:
  /// Returns the current status of the specified named command
  STDMETHOD(QueryStatus)(BSTR bstrCmdName,
                         EnvDTE::vsCommandStatusTextWanted nNeededText,
                         EnvDTE::vsCommandStatus *pnStatusOption,
                         VARIANT *varCommandText);
  /// Execute a given named command
  STDMETHOD(Exec)(BSTR bstrCmdName,
                  EnvDTE::vsCommandExecOption nExecuteOption,
                  VARIANT *pvarVariantIn,
                  VARIANT *pvarVariantOut, VARIANT_BOOL *pvbHandled);

  //////////////////////////////////////////////////////////////////////
  // IDTExtensibility2
public:
  /// Called by our host to setup a connection to this AddIn
  STDMETHOD(OnConnection)(IDispatch *pApplication,
                          AddInDO::ext_ConnectMode nMode,
                          IDispatch *pAddInInst,
                          SAFEARRAY **ppCustom);
  /// Called by our host when this AddIn is un-loaded
  STDMETHOD(OnDisconnection)(AddInDO::ext_DisconnectMode nMode,
                             SAFEARRAY **custom );
  STDMETHOD(OnAddInsUpdate)(SAFEARRAY **custom );
  STDMETHOD(OnStartupComplete)(SAFEARRAY **custom );
  STDMETHOD(OnBeginShutdown)(SAFEARRAY **custom );

  void __stdcall OnClickCfg(IDispatch * /*Office::_CommandBarButton**/ pCtrl,
                            VARIANT_BOOL * pCancelDefault);
  void __stdcall OnClickSay(IDispatch * /*Office::_CommandBarButton**/ pCtrl,
                            VARIANT_BOOL * pCancelDefault);

  typedef IDispEventSimpleImpl</*nID =*/ 1, CDTEAddIn,
    &__uuidof(Office::_CommandBarButtonEvents)> CfgEvents;
  typedef IDispEventSimpleImpl</*nID =*/ 2, CDTEAddIn,
    &__uuidof(Office::_CommandBarButtonEvents)> SayEvents;

private:
  /// Make sure our commands are present & setup any needed toolbars
  void AddCommands(AddInDO::ext_ConnectMode nMode);
  /// Add our commands to Excel 2003
  void AddCommandsExcel2003(AddInDO::ext_ConnectMode nMode);
  /// Add our commands to Visual Studio .Net 2003
  void AddCommandsVS2003(AddInDO::ext_ConnectMode nMode);
  /// Add our commands to Visual Studio 2005
  void AddCommandsVS2005(AddInDO::ext_ConnectMode nMode);
  /// Either get our host to display it's configuration UI, or delegate
  /// to the parent to display our own configuration dialog
  void ConfigureInternal();
  /// Deduce our host based on what interfaces it supports
  Host GuessHostType(IDispatch *pApp);
  /// Remove our command bars, if needed
  void RemoveCommands(AddInDO::ext_DisconnectMode nMode);
  /// Remove our commands from Excel 2003
  void RemoveCommandsExcel2003(AddInDO::ext_DisconnectMode nMode);
  /// Remove our commands from Visual Studio .Net 2003
  void RemoveCommandsVS2003(AddInDO::ext_DisconnectMode nMode);
  /// Remove our commands from Visual Studio 2005
  void RemoveCommandsVS2005(AddInDO::ext_DisconnectMode nMode);
  /// Sink any host-generated events we care about
  void SinkEvents(AddInDO::ext_ConnectMode nMode);
  /// Un-advise an sinks we've setup
  void UnSinkEvents(AddInDO::ext_DisconnectMode nMode);

private:
  /// Command bar name
  static const wchar_t * CMD_BAR_NAME;
  /// Short name of our "Configure" command
  static const CComBSTR CMD_CONFIGURE;
  /// "Configure" command  description
  static const CComBSTR CMD_DSC_CONFIGURE;
  /// Fully qualified name of our "Configure" command
  static const wchar_t * CMD_FULL_CONFIGURE;
  /// Short name of our "SayHello" command
  static const CComBSTR CMD_SAYHELLO;
  /// "SayHello" command  description
  static const CComBSTR CMD_DSC_SAYHELLO;
  /// Fully qualified name of our "SayHello" command
  static const wchar_t * CMD_FULL_SAYHELLO;

private:
  /// Reference on our AddIn instance
  CComPtr<EnvDTE::AddIn> m_pAddIn;
  /// Reference to our host's Application object
  CComPtr<EnvDTE::_DTE> m_pApp;
  /// Reference to our host's Application object
  CComPtr<Excel::_Application> m_pExcel;
  /// Which host are we loaded into
  Host m_nHost;
  /// Non-owning reference to our parent CAddIn instance
  CAddIn *m_pParent;
  /// DTE Window Event Sink
  CWindowEventsSink m_objWindowEvents;
  /// Reference on our host for advising & un-advising of Events
  CComPtr<EnvDTE::_WindowEvents> m_pWinEvents;
  /// Reference on our temporary command bar (not VS 8.0)
  CComPtr<Office::CommandBar> m_pCommandBar;
# if ( SAMPLECAI_COMMAND_BAR_STYLE == SAMPLECAI_COMMAND_BAR_TEMPORARY )
  /// Reference on our temporary command bar (VS 8.0)
  CComPtr<MSVSCBs::CommandBar> m_pCommandBar80;
# endif
  /// Pointer to our "Configure" button in Excel
  CComQIPtr<Office::_CommandBarButton> m_pCfg;
  /// Pointer to our "Say Hello" button in Excel
  CComQIPtr<Office::_CommandBarButton> m_pSay;

  HANDLE	m_hViaGui;
  HANDLE	m_hViaCommands;

}; // End CDTEAddIn.

OBJECT_ENTRY_AUTO(__uuidof(CoDTEAddIn), CDTEAddIn)

// Local Variables:
// fill-column: 72
// indent-tabs-mode: nil
// show-trailing-whitespace: t
// End:

#endif // DTEADDIN_H_E212DF6C_4B8E_4DDE_9653_D9262759406F
